package com.jrx.anytxn.transaction.service.impl;

import com.jrx.anytxn.common.exception.TxnBizException;
import com.jrx.anytxn.common.exception.TxnException;
import com.jrx.anytxn.common.exception.TxnRuntimeException;
import com.jrx.anytxn.common.uitl.DateUtils;
import com.jrx.anytxn.common.uitl.SftpUtils;
import com.jrx.anytxn.customer.entity.CmCustomerFirstLevel;
import com.jrx.anytxn.customer.service.ICustomerService;
import com.jrx.anytxn.param.constant.ErrorMsgConstant;
import com.jrx.anytxn.param.entity.*;
import com.jrx.anytxn.param.mapper.ext.ExtPrVerifyFileTableMapper;
import com.jrx.anytxn.param.service.partner.IPartnerShareProfitService;
import com.jrx.anytxn.param.service.partner.IPmPartnerInfoService;
import com.jrx.anytxn.param.service.system.IBtBatchStatusService;
import com.jrx.anytxn.param.service.system.IOrganizationTableService;
import com.jrx.anytxn.transaction.bean.DebtBean;
import com.jrx.anytxn.transaction.constant.TransBizConstant;
import com.jrx.anytxn.transaction.entity.*;
import com.jrx.anytxn.transaction.mapper.ext.*;
import com.jrx.anytxn.transaction.service.IDebtCalculationService;
import com.jrx.anytxn.transaction.service.IVerifyFileService;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.*;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

@Service
public class VerifyFileServiceImpl implements IVerifyFileService {

    private static final Logger logger = LoggerFactory.getLogger(VerifyFileServiceImpl.class);

    @Autowired
    private IOrganizationTableService organizationTableService;
    @Resource
    private ExtPrVerifyFileTableMapper extPrVerifyFileTableMapper;
    @Resource
    private ExtTlDisbursementLogMapper extTlDisbursementLogMapper;
    @Resource
    private ExtAmLoanMainInfoMapper extAmLoanMainInfoMapper;
    @Autowired
    private ICustomerService customerService;
    @Resource
    private ExtTlPaymentLogMapper extTlPaymentLogMapper;
    @Resource
    private ExtTlPaymentMappingMapper extTlPaymentMappingMapper;
    @Resource
    private ExtTlPaymentAllocationLogMapper extTlPaymentAllocationLogMapper;
    @Resource
    private ExtAmLoanAccountInfoMapper extAmLoanAccountInfoMapper;
    @Autowired
    private IPmPartnerInfoService pmPartnerInfoService;
    @Autowired
    private IPartnerShareProfitService partnerShareProfitService;
    @Autowired
    private IDebtCalculationService debtCalculationService;
    @Resource
    private ExtAmRepaymentPlanInfoMapper extAmRepaymentPlanInfoMapper;
    @Autowired
    private IBtBatchStatusService btBatchStatusService;


    @Override
    public void createVerifyFile(List<PrProductTable> productTable, String filePath, String fileName, Integer verifyPoolSize) throws TxnBizException {
        PrOrganizationTable org = organizationTableService.findByOrgIdForBatch(TransBizConstant.DEFAULT_ORG_ID);
        String toDay = DateUtils.format(org.getToday(),"yyyyMMdd");

        //按照产品生成文件
        for(PrProductTable table : productTable){
            String verifyPath = filePath + org.getTenantId() + File.separator + toDay + File.separator + table.getProductId() + File.separator;

            //获取对应对账文件配置
            PrVerifyFileTable verifyFileTable = extPrVerifyFileTableMapper.selectByVerifyFileIdAndTenantId(table.getVerifyFileId(),table.getTenantId());
            if(null == verifyFileTable){
                continue;
            }
            String fileTypes = verifyFileTable.getVerifyFileType();
            if(fileTypes.contains(TransBizConstant.VERIFY_FILE_TYPE_03)){
                String fName = table.getProductId() + "_" + toDay +"_" + TransBizConstant.VERIFY_FILE_NAME_LOAN + "_" + fileName + ".txt";
                //没有数据也生成空文件
                createFolder(verifyPath,fName);
                //获取数据
                List<TlDisbursementLog> logList = extTlDisbursementLogMapper.selectByProductIdAndSumStatusAndBusDate(
                        table.getProductId(),table.getTenantId(),TransBizConstant.DISBURSEMENT_LOG_SUM_STATUS_S,org.getToday());
                if(CollectionUtils.isNotEmpty(logList)){
                    //多线程处理文件信息  单线程生成文件
                    buildLoanFile(logList,verifyPoolSize,verifyPath,fName,toDay);
                }
            }
            if(fileTypes.contains(TransBizConstant.VERIFY_FILE_TYPE_04)){
                //获取分润参数
                PrShareProfitTable prShareProfitTable = null;
                if(null != table.getPartnerId()){
                    //获取合作伙伴信息
                    PmPartnerInfo pmPartnerInfo = pmPartnerInfoService.getByPartnerId(
                            table.getTenantId(),table.getPartnerId());

                    //获取合作伙伴分润信息
                    if(null != pmPartnerInfo && null != pmPartnerInfo.getProfitId()){
                        prShareProfitTable = partnerShareProfitService.getByShareProfitId(
                                pmPartnerInfo.getTenantId(),pmPartnerInfo.getProfitId());
                    }
                }
                String fName = table.getProductId() + "_" + toDay +"_" + TransBizConstant.VERIFY_FILE_NAME_PAYMENT + "_" + fileName + ".txt";
                //没有数据也生成空文件
                createFolder(verifyPath,fName);

                List<TlPaymentLog> logList = extTlPaymentLogMapper.selectByProductIdAndBusiDate(table.getProductId(),table.getTenantId(),
                        TransBizConstant.PAYMENT_LOG_SUM_STATUS_S,org.getToday());
                if(CollectionUtils.isNotEmpty(logList)){
                    //多线程处理文件信息  单线程生成文件
                    buildPaymentFile(logList,verifyPoolSize,verifyPath,fName,toDay,prShareProfitTable,TransBizConstant.VERIFY_FILE_TYPE_04);
                }
            }
            if(fileTypes.contains(TransBizConstant.VERIFY_FILE_TYPE_05)||
                    fileTypes.contains(TransBizConstant.VERIFY_FILE_TYPE_06)){

                if(fileTypes.contains(TransBizConstant.VERIFY_FILE_TYPE_05)){
                    String fName = table.getProductId() + "_" + toDay +"_" + TransBizConstant.VERIFY_FILE_NAME_TMR_DUE + "_" + fileName + ".txt";
                    //没有数据也生成空文件
                    createFolder(verifyPath,fName);
                    //按照逾期或者划款日查询
                    List<AmLoanAccountInfo> accountList = extAmLoanAccountInfoMapper.selectByNextPaymentDateOrAccountStatus(
                            table.getProductId(),org.getNextProcessingDate(),TransBizConstant.ACCOUNT_STATUS_2
                    );
                    if(CollectionUtils.isNotEmpty(accountList)){
                        //多线程处理文件信息  单线程生成文件
                        buildDueFile(accountList,verifyPoolSize,verifyPath,fName,toDay,org,TransBizConstant.VERIFY_FILE_TYPE_05);
                    }
                }
                if(fileTypes.contains(TransBizConstant.VERIFY_FILE_TYPE_06)){
                    String fName = table.getProductId() + "_" + toDay +"_" + TransBizConstant.VERIFY_FILE_NAME_OVERDUE + "_" + fileName + ".txt";
                    createFolder(verifyPath,fName);
                    //查询逾期订单
                    List<AmLoanAccountInfo> overList = extAmLoanAccountInfoMapper.selectByProIdOrAccountStatus(
                            table.getProductId(),TransBizConstant.ACCOUNT_STATUS_2
                    );
                    if(CollectionUtils.isNotEmpty(overList)){
                        //多线程处理文件信息  单线程生成文件
                        buildDueFile(overList,verifyPoolSize,verifyPath,fName,toDay,org,TransBizConstant.VERIFY_FILE_TYPE_06);
                    }
                }
            }
            if(fileTypes.contains(TransBizConstant.VERIFY_FILE_TYPE_07)){
                String fName = table.getProductId() + "_" + toDay +"_" + TransBizConstant.VERIFY_FILE_NAME_CMPS + "_" + fileName + ".txt";
                //没有数据也生成空文件
                createFolder(verifyPath,fName);
                //代偿日期选择当天，代偿是切日后发起的交易
                List<TlPaymentLog> logList = extTlPaymentLogMapper.selectByProIdAndBusiDateAndType(table.getProductId(),table.getTenantId(),
                        TransBizConstant.PAYMENT_LOG_SUM_STATUS_S,org.getNextProcessingDate(),TransBizConstant.REPAYMENT_TYPE_CMPS);
                if(CollectionUtils.isNotEmpty(logList)){
                    //多线程处理文件信息  单线程生成文件
                    buildPaymentFile(logList,verifyPoolSize,verifyPath,fName,toDay,null,TransBizConstant.VERIFY_FILE_TYPE_07);
                }
            }
            if(fileTypes.contains(TransBizConstant.VERIFY_FILE_TYPE_08)){

                String fName = table.getProductId() + "_" + toDay +"_" + TransBizConstant.VERIFY_FILE_NAME_CRT + "_" + fileName + ".txt";
                //没有数据也生成空文件
                createFolder(verifyPath,fName);

                List<TlPaymentLog> logList = extTlPaymentLogMapper.selectByProIdAndBusiDateAndType(table.getProductId(),table.getTenantId(),
                        TransBizConstant.PAYMENT_LOG_SUM_STATUS_S,org.getToday(),TransBizConstant.REPAYMENT_TYPE_CRT);
                if(CollectionUtils.isNotEmpty(logList)){
                    //多线程处理文件信息  单线程生成文件
                    buildPaymentFile(logList,verifyPoolSize,verifyPath,fName,toDay,null,TransBizConstant.VERIFY_FILE_TYPE_08);
                }
            }
        }
    }

    @Override
    public void createAutoPaymentFile(List<PrProductTable> productTableList, String filePath, String fileName, Integer verifyPoolSize) throws Exception {
        if(CollectionUtils.isEmpty(productTableList)){
            logger.info("没有需要生成对账文件的产品");
            return;
        }

        PrOrganizationTable org = organizationTableService.findByOrgIdForBatch(TransBizConstant.DEFAULT_ORG_ID);
        String toDay = DateUtils.format(org.getNextProcessingDate(),"yyyyMMdd");

        //查询当日批扣是否执行完成
        int autoPaymentType = btBatchStatusService.countByJobNameAndBusiDateAndStatus(TransBizConstant.AUTO_PAYMENT,
                org.getNextProcessingDate(),org.getTenantId(),TransBizConstant.BATCH_SATTUS_2);
        //批扣没有完成直接返回
        if(autoPaymentType == 0){
            logger.info("批扣未执行或执行中");
            return;
        }

        //查询是否存在处理中的批扣流水
        int countNumber = extTlPaymentLogMapper.countByAutoPaymentTypeAndSumStatusList(
                Arrays.asList(TransBizConstant.PAYMENT_LOG_SUM_STATUS_T,TransBizConstant.PAYMENT_LOG_SUM_STATUS_D,TransBizConstant.PAYMENT_LOG_SUM_STATUS_O,TransBizConstant.PAYMENT_LOG_SUM_STATUS_P),
                org.getNextProcessingDate(),TransBizConstant.REPAYMENT_TYPE_AUTO,autoPaymentType+"");
        if(countNumber > 0){
            logger.info("存在未完成的批扣流水");
            return;
        }

        for(PrProductTable table : productTableList){
            PrVerifyFileTable verifyFileTable = extPrVerifyFileTableMapper.selectByVerifyFileIdAndTenantId(table.getVerifyFileId(),table.getTenantId());
            if(verifyFileTable.getVerifyFileType().contains(TransBizConstant.VERIFY_FILE_TYPE_09)){
                String verifyPath = filePath + org.getTenantId() + File.separator + toDay + File.separator + table.getProductId() + File.separator;

                String fName = table.getProductId() + "_" + toDay +"_" + TransBizConstant.VERIFY_FILE_NAME_AUTO_PAYMENT + "_" + autoPaymentType + "_" + fileName + ".txt";

                File file = new File(verifyPath + fName);
                if(!file.exists()){
                    //生成文件
                    createFolder(verifyPath,fName);
                    //查询还款流水
                    List<TlPaymentLog> logList = extTlPaymentLogMapper.selectByProIdAndAntoPaymentType(
                            table.getProductId(),table.getTenantId(),TransBizConstant.PAYMENT_LOG_SUM_STATUS_S,org.getNextProcessingDate(),
                            TransBizConstant.REPAYMENT_TYPE_AUTO,autoPaymentType+"");

                    if(CollectionUtils.isNotEmpty(logList)){
                        buildPaymentFile(logList,verifyPoolSize,verifyPath,fName,toDay,null,TransBizConstant.VERIFY_FILE_TYPE_09);
                    }
                }
            }
        }
    }

    @Override
    public void mergeVerifyFile(List<PrProductTable> productTableList, String filePath, String fileName) throws IOException {
        PrOrganizationTable org = organizationTableService.findByOrgIdForBatch(TransBizConstant.DEFAULT_ORG_ID);
        String toDay = DateUtils.format(org.getToday(),"yyyyMMdd");
        if(CollectionUtils.isNotEmpty(productTableList)){
            for(PrProductTable table : productTableList){
                String verifyPath = filePath + org.getTenantId() + File.separator + toDay + File.separator + table.getProductId() + File.separator;

                PrVerifyFileTable verifyFileTable = extPrVerifyFileTableMapper.selectByVerifyFileIdAndTenantId(table.getVerifyFileId(),table.getTenantId());
                if(null == verifyFileTable){
                    continue;
                }
                //累计，当日对账文件不需要合并
                String verifyType = verifyFileTable.getVerifyFileType();
                if(verifyType.contains(TransBizConstant.VERIFY_FILE_TYPE_03)){
                    String fileType = table.getProductId() + "_" + toDay + "_" + TransBizConstant.VERIFY_FILE_NAME_LOAN;
                    mergeVerifyFile(verifyPath,fileType);
                }
                if(verifyType.contains(TransBizConstant.VERIFY_FILE_TYPE_04)){
                    String fileType = table.getProductId() + "_" + toDay + "_" + TransBizConstant.VERIFY_FILE_NAME_PAYMENT;
                    mergeVerifyFile(verifyPath,fileType);
                }
                if(verifyType.contains(TransBizConstant.VERIFY_FILE_TYPE_05)){
                    String fileType = table.getProductId() + "_" + toDay + "_" + TransBizConstant.VERIFY_FILE_NAME_TMR_DUE;
                    mergeVerifyFile(verifyPath,fileType);
                }
                if(verifyType.contains(TransBizConstant.VERIFY_FILE_TYPE_06)){
                    String fileType = table.getProductId() + "_" + toDay + "_" + TransBizConstant.VERIFY_FILE_NAME_OVERDUE;
                    mergeVerifyFile(verifyPath,fileType);
                }
                if(verifyType.contains(TransBizConstant.VERIFY_FILE_TYPE_07)){
                    String fileType = table.getProductId() + "_" + toDay + "_" + TransBizConstant.VERIFY_FILE_NAME_CMPS;
                    mergeVerifyFile(verifyPath,fileType);
                }
                if(verifyType.contains(TransBizConstant.VERIFY_FILE_TYPE_08)){
                    String fileType = table.getProductId() + "_" + toDay + "_" + TransBizConstant.VERIFY_FILE_NAME_CRT;
                    mergeVerifyFile(verifyPath,fileType);
                }
                if(verifyType.contains(TransBizConstant.VERIFY_FILE_TYPE_09)){
                    int autoPaymentCount = btBatchStatusService.countByJobNameAndBusiDateAndStatus(
                            TransBizConstant.AUTO_PAYMENT,org.getToday(),org.getTenantId(),TransBizConstant.BATCH_SATTUS_2
                    );
                    if(autoPaymentCount == 0){
                        continue;
                    }
                    for(int i = 1; i <= autoPaymentCount; i++){
                        String fileType = table.getProductId() + "_" + toDay + "_" + TransBizConstant.VERIFY_FILE_NAME_AUTO_PAYMENT + "_" + i;
                        mergeVerifyFile(verifyPath,fileType);
                    }
                }
                String okName = table.getProductId() + "_" + toDay + ".ok";
                File okFile = new File(verifyPath + okName);
                if(!okFile.exists()) {
                    okFile.createNewFile();//按照产品生成OK文件
                }
            }
        }
    }

    @Override
    public void uploadVerifyFile(List<PrProductTable> productTableList, String filePath) throws Exception {
        PrOrganizationTable org = organizationTableService.findByOrgIdForBatch(TransBizConstant.DEFAULT_ORG_ID);
        String toDay = DateUtils.format(org.getToday(),"yyyyMMdd");
        if(CollectionUtils.isNotEmpty(productTableList)){
            for(PrProductTable table : productTableList){
                String verifyPath = filePath + org.getTenantId() + File.separator + toDay + File.separator + table.getProductId() + File.separator;

                PrVerifyFileTable verifyFileTable = extPrVerifyFileTableMapper.selectByVerifyFileIdAndTenantId(table.getVerifyFileId(),table.getTenantId());
                if(null == verifyFileTable){
                    continue;
                }

                String verifyType = verifyFileTable.getVerifyFileType();

                List<String> uploadFileLists = new ArrayList<>();
                if(verifyType.contains(TransBizConstant.VERIFY_FILE_TYPE_01)){
                    String fileType = table.getProductId() + "_" + toDay + "_" + TransBizConstant.VERIFY_FILE_NAME_GENERAL_ALL + ".txt";
                    uploadFileLists.add(fileType);
                }
                if(verifyType.contains(TransBizConstant.VERIFY_FILE_TYPE_02)){
                    String fileType = table.getProductId() + "_" + toDay + "_" + TransBizConstant.VERIFY_FILE_NAME_GENERAL_TODAY + ".txt";
                    uploadFileLists.add(fileType);
                }
                if(verifyType.contains(TransBizConstant.VERIFY_FILE_TYPE_03)){
                    String fileType = table.getProductId() + "_" + toDay + "_" + TransBizConstant.VERIFY_FILE_NAME_LOAN + ".txt";
                    uploadFileLists.add(fileType);
                }
                if(verifyType.contains(TransBizConstant.VERIFY_FILE_TYPE_04)){
                    String fileType = table.getProductId() + "_" + toDay + "_" + TransBizConstant.VERIFY_FILE_NAME_PAYMENT + ".txt";
                    uploadFileLists.add(fileType);
                }
                if(verifyType.contains(TransBizConstant.VERIFY_FILE_TYPE_05)){
                    String fileType = table.getProductId() + "_" + toDay + "_" + TransBizConstant.VERIFY_FILE_NAME_TMR_DUE + ".txt";
                    uploadFileLists.add(fileType);
                }
                if(verifyType.contains(TransBizConstant.VERIFY_FILE_TYPE_06)){
                    String fileType = table.getProductId() + "_" + toDay + "_" + TransBizConstant.VERIFY_FILE_NAME_OVERDUE + ".txt";
                    uploadFileLists.add(fileType);
                }
                if(verifyType.contains(TransBizConstant.VERIFY_FILE_TYPE_07)){
                    String fileType = table.getProductId() + "_" + toDay + "_" + TransBizConstant.VERIFY_FILE_NAME_CMPS + ".txt";
                    uploadFileLists.add(fileType);
                }
                if(verifyType.contains(TransBizConstant.VERIFY_FILE_TYPE_08)){
                    String fileType = table.getProductId() + "_" + toDay + "_" + TransBizConstant.VERIFY_FILE_NAME_CRT + ".txt";
                    uploadFileLists.add(fileType);
                }
                if(verifyType.contains(TransBizConstant.VERIFY_FILE_TYPE_09)){
                    int autoPaymentCount = btBatchStatusService.countByJobNameAndBusiDateAndStatus(
                            TransBizConstant.AUTO_PAYMENT,org.getToday(),org.getTenantId(),TransBizConstant.BATCH_SATTUS_2
                    );
                    if(autoPaymentCount != 0){
                        for(int i = 1; i <= autoPaymentCount; i++){
                            String fileType = table.getProductId() + "_" + toDay + "_" + TransBizConstant.VERIFY_FILE_NAME_AUTO_PAYMENT + "_" + i + ".txt";
                            uploadFileLists.add(fileType);
                        }
                    }
                }
                //调用上传接口
                uploadFile(uploadFileLists,verifyFileTable,verifyPath,org,table.getProductId());
            }
        }
    }

    private void createFolder(String basePath,String fileName){
        Path verifyFile = Paths.get(basePath + fileName);
        Path pFile = Paths.get(basePath);

        if (!Files.exists(verifyFile)) {
            //判断文件夹是否存在
            if (!Files.isDirectory(pFile)) {
                try {
                    Files.createDirectories(pFile);
                } catch (IOException e) {
                    logger.error("创建目录失败",e);
                }
            }
            //创建文件
            try {
                Files.createFile(verifyFile);
            } catch (IOException e) {
                logger.error("创建文件失败",e);
            }
        }
    }

    private void buildLoanFile(List<TlDisbursementLog> logList, Integer collectionPoolSize, String collrctionPath, String fileName, String toDay){
        List<String> messageList = Collections.synchronizedList(new ArrayList<String>());

        //多线程处理
        int size = logList.size();
        int tl = size % collectionPoolSize == 0 ? size / collectionPoolSize : (size
                / collectionPoolSize + 1);
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(collectionPoolSize);
        List<Future<String>> futures = new ArrayList<>(collectionPoolSize);
        for (int i = 0; i < collectionPoolSize; i++) {
            int end = (i + 1) * tl;
            if(i * tl >= size){
                break;
            }
            List<TlDisbursementLog> proList = logList.subList(i * tl, Math.min(end, size));
            Callable<String> task = () -> {
                String message = "S";
                createLoanFileMessage(proList,toDay,messageList);
                return message;
            };
            futures.add(fixedThreadPool.submit(task));
        }
        //获取处理结果
        for (Future<String> future : futures) {
            try {
                future.get();
            } catch (Exception e) {
                logger.error("生成放款对账文件异常 : " ,e);
                throw new RuntimeException(e);
            }
        }
        fixedThreadPool.shutdown();
        logger.error("开始生成放款对账文件");
        generatingFile(messageList,collrctionPath ,fileName);
    }

    private void buildPaymentFile(List<TlPaymentLog> logList, Integer collectionPoolSize, String collrctionPath,
                                  String fileName, String toDay,PrShareProfitTable prShareProfitTable,String fileType){
        List<String> messageList = Collections.synchronizedList(new ArrayList<String>());

        //多线程处理
        int size = logList.size();
        int tl = size % collectionPoolSize == 0 ? size / collectionPoolSize : (size
                / collectionPoolSize + 1);
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(collectionPoolSize);
        List<Future<String>> futures = new ArrayList<>(collectionPoolSize);
        for (int i = 0; i < collectionPoolSize; i++) {
            int end = (i + 1) * tl;
            if(i * tl >= size){
                break;
            }
            List<TlPaymentLog> proList = logList.subList(i * tl, Math.min(end, size));
            Callable<String> task = () -> {
                String message = "S";
                if(TransBizConstant.VERIFY_FILE_TYPE_04.equals(fileType)){
                    createPaymentFileMessage(proList,toDay,messageList,prShareProfitTable);
                }else if(TransBizConstant.VERIFY_FILE_TYPE_07.equals(fileType)){
                    createCmpsFileMessage(proList,toDay,messageList);
                }else if(TransBizConstant.VERIFY_FILE_TYPE_08.equals(fileType)){
                    createCrtFileMessage(proList,toDay,messageList);
                }else if(TransBizConstant.VERIFY_FILE_TYPE_09.equals(fileType)){
                    createAutoPaymentFileMessage(proList,toDay,messageList);
                }
                return message;
            };
            futures.add(fixedThreadPool.submit(task));
        }
        //获取处理结果
        for (Future<String> future : futures) {
            try {
                future.get();
            } catch (Exception e) {
                logger.error("生成还款对账文件异常 : " ,e);
                throw new RuntimeException(e);
            }
        }
        fixedThreadPool.shutdown();
        logger.error("开始生成还款对账文件");
        generatingFile(messageList,collrctionPath ,fileName);
    }

    private void buildDueFile(List<AmLoanAccountInfo> accountList, Integer collectionPoolSize, String collrctionPath,
                              String fileName, String toDay,PrOrganizationTable org,String type){
        List<String> messageList = Collections.synchronizedList(new ArrayList<String>());

        //多线程处理
        int size = accountList.size();
        int tl = size % collectionPoolSize == 0 ? size / collectionPoolSize : (size
                / collectionPoolSize + 1);
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(collectionPoolSize);
        List<Future<String>> futures = new ArrayList<>(collectionPoolSize);
        for (int i = 0; i < collectionPoolSize; i++) {
            int end = (i + 1) * tl;
            if(i * tl >= size){
                break;
            }
            List<AmLoanAccountInfo> proList = accountList.subList(i * tl, Math.min(end, size));
            Callable<String> task = () -> {
                String message = "S";
                if(TransBizConstant.VERIFY_FILE_TYPE_05.equals(type)){
                    createDueFileMessage(proList,toDay,messageList,org);
                }else if(TransBizConstant.VERIFY_FILE_TYPE_06.equals(type)){
                    createOverFileMessage(proList,toDay,messageList,org);
                }
                return message;
            };
            futures.add(fixedThreadPool.submit(task));
        }
        //获取处理结果
        for (Future<String> future : futures) {
            try {
                future.get();
            } catch (Exception e) {
                logger.error("生成对账文件异常 : " ,e);
                throw new RuntimeException(e);
            }
        }
        fixedThreadPool.shutdown();
        logger.error("开始生成对账文件");
        generatingFile(messageList,collrctionPath ,fileName);
    }

    private void createLoanFileMessage(List<TlDisbursementLog> proList,String toDay,List<String> messageList) throws TxnException {
        for(TlDisbursementLog log : proList){
            StringBuffer sb = new StringBuffer();
            sb.append(toDay + TransBizConstant.separator);
            AmLoanMainInfo mainInfo = extAmLoanMainInfoMapper.selectByLoanIdAndTenantId(log.getLoanId(),log.getTenantId());
            sb.append((mainInfo.getContractNumber()==null?"":mainInfo.getContractNumber()) + TransBizConstant.separator);
            sb.append(log.getLoanId() + TransBizConstant.separator);
            sb.append((mainInfo.getMerchantId()==null?"":mainInfo.getMerchantId()) + TransBizConstant.separator);
            String txnTime = DateUtils.format(mainInfo.getTxnTime(),"yyyy-MM-dd HH:mm:ss");
            sb.append(txnTime + TransBizConstant.separator);
            String lastPaymentDate = DateUtils.format(mainInfo.getLastPaymentDate(),"yyyy-MM-dd");
            sb.append(lastPaymentDate + TransBizConstant.separator);
            CmCustomerFirstLevel firstLevel = customerService.getFirstLevelByCondition(
                    log.getCustomerId(),log.getOrganizationId(),log.getTenantId());
            sb.append(firstLevel.getChineseName() + TransBizConstant.separator);
            sb.append(firstLevel.getIdNumber() + TransBizConstant.separator);
            sb.append(log.getAmount() + TransBizConstant.separator);
            sb.append(mainInfo.getInterestRate().setScale(10, BigDecimal.ROUND_HALF_UP) + TransBizConstant.separator);
            sb.append(mainInfo.getPaymentDateDd() + TransBizConstant.separator);
            String firstPaymentDate = DateUtils.format(mainInfo.getFirstPaymentDate(),"yyyy-MM-dd");
            sb.append(firstPaymentDate + TransBizConstant.separator);
            sb.append(mainInfo.getTotalTenor() + TransBizConstant.separator);
            sb.append("正常" + TransBizConstant.separator);
            sb.append(log.getSeqNo());
            messageList.add(sb.toString());
        }
    }

    private void createPaymentFileMessage(List<TlPaymentLog> proList,String toDay,List<String> messageList,PrShareProfitTable prShareProfitTable) throws TxnException {
        for(TlPaymentLog log : proList){
            //账单分期，贴息自动扣款 不计算
            if(TransBizConstant.REPAYMENT_TYPE_STAGING.equals(log.getPaymentType())||
                    TransBizConstant.REPAYMENT_TYPE_WAIVEAUTO.equals(log.getPaymentType())){
                continue;
            }

            List<TlPaymentMapping> mappingList = extTlPaymentMappingMapper.selectByPaymentSeqAndCustomerId(log.getSeqNo(),log.getCustomerId(),log.getTenantId());

            CmCustomerFirstLevel firstLevel = customerService.getFirstLevelByCondition(
                    log.getCustomerId(),log.getOrganizationId(),log.getTenantId());

            for(TlPaymentMapping mapping : mappingList){
                StringBuffer sb = new StringBuffer();
                sb.append(toDay + TransBizConstant.separator);
                AmLoanMainInfo mainInfo = extAmLoanMainInfoMapper.selectByLoanIdAndTenantId(mapping.getLoanId(),mapping.getTenantId());
                sb.append((mainInfo.getContractNumber()==null?"":mainInfo.getContractNumber()) + TransBizConstant.separator);
                sb.append(mapping.getLoanId() + TransBizConstant.separator);
                sb.append((mainInfo.getMerchantId()==null?"":mainInfo.getMerchantId()) + TransBizConstant.separator);
                String updateTime = DateUtils.format(log.getCreateTime(),"yyyy-MM-dd HH:mm:ss");
                sb.append(updateTime + TransBizConstant.separator);
                String loanTime = DateUtils.format(mainInfo.getTxnTime(),"yyyy-MM-dd HH:mm:ss");
                sb.append(loanTime + TransBizConstant.separator);
                String lastPaymentDate = DateUtils.format(mainInfo.getLastPaymentDate(),"yyyy-MM-dd");
                sb.append(lastPaymentDate + TransBizConstant.separator);
                sb.append(firstLevel.getChineseName() + TransBizConstant.separator);
                sb.append(firstLevel.getIdNumber() + TransBizConstant.separator);
                sb.append(mainInfo.getLoanAmount() + TransBizConstant.separator);
                sb.append(mainInfo.getInterestRate().setScale(10, BigDecimal.ROUND_HALF_UP) + TransBizConstant.separator);
                sb.append(mainInfo.getTotalTenor() + TransBizConstant.separator);//总期数
                //查询还款分配历史表
                List<TlPaymentAllocationLog> allList = extTlPaymentAllocationLogMapper.findCustLog(
                        mainInfo.getLoanId(),log.getSeqNo(),log.getCustomerId(),log.getTenantId());
                //如果是提前结清 还款期数为最后一期
                if(TransBizConstant.REPAYMENT_TYPE_PRETERMINTION.equals(log.getPaymentType())){
                    sb.append(mainInfo.getTotalTenor() + TransBizConstant.separator);
                }else{
                    sb.append(allList.get(0).getBillingTenor() + TransBizConstant.separator);
                }
                AmLoanAccountInfo accountInfo = extAmLoanAccountInfoMapper.selectByLoanId(
                        mainInfo.getLoanId(),log.getCustomerId(),mainInfo.getTenantId());
                sb.append(accountInfo.getPrincipalBalance() + TransBizConstant.separator);
                sb.append(accountInfo.getDelqDays() + TransBizConstant.separator);

                countPaymentAmount(allList,sb,log,prShareProfitTable);
                if(TransBizConstant.REPAYMENT_TYPE_PAY.equals(log.getPaymentType())){
                    sb.append("正常还款" + TransBizConstant.separator);
                }else if(TransBizConstant.REPAYMENT_TYPE_PREPAY.equals(log.getPaymentType())){
                    sb.append("提前还款" + TransBizConstant.separator);
                }else if(TransBizConstant.REPAYMENT_TYPE_PREPAY_CURR.equals(log.getPaymentType())){
                    sb.append("提前还当期" + TransBizConstant.separator);
                }else if(TransBizConstant.REPAYMENT_TYPE_PRETERMINTION.equals(log.getPaymentType())){
                    sb.append("提前结清" + TransBizConstant.separator);
                }else if(TransBizConstant.REPAYMENT_TYPE_OVERDUE.equals(log.getPaymentType())){
                    sb.append("逾期还款" + TransBizConstant.separator);
                }else if(TransBizConstant.REPAYMENT_TYPE_AUTO.equals(log.getPaymentType())){
                    sb.append("自动批扣" + TransBizConstant.separator);
                }else if(TransBizConstant.REPAYMENT_TYPE_CMPS.equals(log.getPaymentType())){
                    sb.append("代偿还款" + TransBizConstant.separator);
                }else if(TransBizConstant.REPAYMENT_TYPE_CRT.equals(log.getPaymentType())){
                    sb.append("回购" + TransBizConstant.separator);
                }else if(TransBizConstant.REPAYMENT_TYPE_BILLOVERDUEPAY.equals(log.getPaymentType())){
                    sb.append("账单逾期还款" + TransBizConstant.separator);
                }else if(TransBizConstant.REPAYMENT_TYPE_BILLPAY.equals(log.getPaymentType())){
                    sb.append("账单正常还款" + TransBizConstant.separator);
                }else if(TransBizConstant.REPAYMENT_TYPE_BILLPREPAYCURR.equals(log.getPaymentType())){
                    sb.append("账单提前还当期" + TransBizConstant.separator);
                }else if(TransBizConstant.REPAYMENT_TYPE_PAY_TERM.equals(log.getPaymentType())){
                    sb.append("指定期次还款" + TransBizConstant.separator);
                }

                if(TransBizConstant.ACCOUNT_STATUS_2.equals(accountInfo.getAccountStatus())){
                    sb.append("逾期");
                }else if(TransBizConstant.ACCOUNT_STATUS_7.equals(accountInfo.getAccountStatus())||
                        TransBizConstant.ACCOUNT_STATUS_8.equals(accountInfo.getAccountStatus())){
                    sb.append("结清");
                }else{
                    sb.append("正常");
                }
                messageList.add(sb.toString());
            }
        }
    }

    private void createDueFileMessage(List<AmLoanAccountInfo> proList,String toDay,List<String> messageList,PrOrganizationTable org) throws TxnException {
        for(AmLoanAccountInfo info : proList){
            StringBuffer sb = new StringBuffer();
            sb.append(toDay + TransBizConstant.separator);
            AmLoanMainInfo mainInfo = extAmLoanMainInfoMapper.selectByLoanIdAndTenantId(info.getLoanId(),info.getTenantId());
            sb.append((mainInfo.getContractNumber()==null?"":mainInfo.getContractNumber()) + TransBizConstant.separator);
            sb.append(info.getLoanId() + TransBizConstant.separator);
            sb.append((mainInfo.getMerchantId()==null?"":mainInfo.getMerchantId()) + TransBizConstant.separator);
            String txnTime = DateUtils.format(mainInfo.getTxnTime(),"yyyy-MM-dd HH:mm:ss");
            sb.append(txnTime + TransBizConstant.separator);
            String lastPaymentDate = DateUtils.format(mainInfo.getLastPaymentDate(),"yyyy-MM-dd");
            sb.append(lastPaymentDate + TransBizConstant.separator);
            CmCustomerFirstLevel firstLevel = customerService.getFirstLevelByCondition(
                    info.getCustomerId(),info.getOrganizationId(),info.getTenantId());
            sb.append(firstLevel.getChineseName() + TransBizConstant.separator);
            sb.append(firstLevel.getIdNumber() + TransBizConstant.separator);
            sb.append(mainInfo.getLoanAmount() + TransBizConstant.separator);
            sb.append(mainInfo.getInterestRate().setScale(10, BigDecimal.ROUND_HALF_UP) + TransBizConstant.separator);
            sb.append(mainInfo.getTotalTenor() + TransBizConstant.separator);
            sb.append(info.getCastTenor() + TransBizConstant.separator);
            String paymentDate = DateUtils.format(info.getNextPaymentDate(),"yyyy-MM-dd");
            sb.append(paymentDate + TransBizConstant.separator);
            //计算欠款
            DebtBean debtBean;
            if(TransBizConstant.ACCOUNT_STATUS_2.equals(info.getAccountStatus())){
                debtBean = debtCalculationService.getBalance(info,org.getNextProcessingDate(), true, null, null, false);
            }else{
                debtBean = debtCalculationService.getBalance(info,org.getNextProcessingDate(), null, true, null, false);
            }
            sb.append(debtBean.getTotalAmount() + TransBizConstant.separator);
            sb.append(debtBean.getPrincipalAmount() + TransBizConstant.separator);
            sb.append(debtBean.getInterestAmount() + TransBizConstant.separator);
            sb.append(debtBean.getFeeAmount() + TransBizConstant.separator);
            sb.append(debtBean.getPenaltyAmount() + TransBizConstant.separator);
            sb.append(debtBean.getCompountAmount());
            messageList.add(sb.toString());
        }
    }

    private void createCmpsFileMessage(List<TlPaymentLog> proList,String toDay,List<String> messageList) throws TxnException {
        for(TlPaymentLog log : proList){
            List<TlPaymentMapping> mappingList = extTlPaymentMappingMapper.selectByPaymentSeqAndCustomerId(log.getSeqNo(),log.getCustomerId(),log.getTenantId());

            for(TlPaymentMapping mapping : mappingList){
                StringBuffer sb = new StringBuffer();
                sb.append(toDay + TransBizConstant.separator);
                AmLoanMainInfo mainInfo = extAmLoanMainInfoMapper.selectByLoanIdAndTenantId(mapping.getLoanId(),mapping.getTenantId());
                sb.append((mainInfo.getContractNumber()==null?"":mainInfo.getContractNumber()) + TransBizConstant.separator);
                sb.append(mapping.getLoanId() + TransBizConstant.separator);
                sb.append((mainInfo.getMerchantId()==null?"":mainInfo.getMerchantId()) + TransBizConstant.separator);
                String updateTime = DateUtils.format(log.getCreateTime(),"yyyy-MM-dd HH:mm:ss");
                sb.append(updateTime + TransBizConstant.separator);
                String loanTime = DateUtils.format(mainInfo.getTxnTime(),"yyyy-MM-dd HH:mm:ss");
                sb.append(loanTime + TransBizConstant.separator);
                String lastPaymentDate = DateUtils.format(mainInfo.getLastPaymentDate(),"yyyy-MM-dd");
                sb.append(lastPaymentDate + TransBizConstant.separator);
                CmCustomerFirstLevel firstLevel = customerService.getFirstLevelByCondition(
                        log.getCustomerId(),log.getOrganizationId(),log.getTenantId());
                sb.append(firstLevel.getChineseName() + TransBizConstant.separator);
                sb.append(firstLevel.getIdNumber() + TransBizConstant.separator);
                sb.append(mainInfo.getLoanAmount() + TransBizConstant.separator);
                sb.append(mainInfo.getInterestRate().setScale(10, BigDecimal.ROUND_HALF_UP) + TransBizConstant.separator);
                sb.append(mainInfo.getTotalTenor() + TransBizConstant.separator);//总期数
                //查询还款分配历史表
                List<TlPaymentAllocationLog> allList = extTlPaymentAllocationLogMapper.findCustLog(
                        mainInfo.getLoanId(),log.getSeqNo(),log.getCustomerId(),log.getTenantId());
                sb.append(allList.get(0).getBillingTenor() + TransBizConstant.separator);

                AmLoanAccountInfo accountInfo = extAmLoanAccountInfoMapper.selectByLoanId(
                        mainInfo.getLoanId(),log.getCustomerId(),mainInfo.getTenantId());
                sb.append(accountInfo.getPrincipalBalance() + TransBizConstant.separator);
                sb.append(accountInfo.getDelqDays() + TransBizConstant.separator);

                countCmpsAmount(allList,sb);
                sb.append("代偿还款" + TransBizConstant.separator);
                if(TransBizConstant.ACCOUNT_STATUS_2.equals(accountInfo.getAccountStatus())){
                    sb.append("逾期");
                }else if(TransBizConstant.ACCOUNT_STATUS_7.equals(accountInfo.getAccountStatus())||
                        TransBizConstant.ACCOUNT_STATUS_8.equals(accountInfo.getAccountStatus())){
                    sb.append("结清");
                }else{
                    sb.append("正常");
                }
                messageList.add(sb.toString());
            }
        }
    }

    private void createCrtFileMessage(List<TlPaymentLog> proList,String toDay,List<String> messageList) throws TxnException {
        for(TlPaymentLog log : proList){
            List<TlPaymentMapping> mappingList = extTlPaymentMappingMapper.selectByPaymentSeqAndCustomerId(log.getSeqNo(),log.getCustomerId(),log.getTenantId());

            for(TlPaymentMapping mapping : mappingList){
                StringBuffer sb = new StringBuffer();
                sb.append(toDay + TransBizConstant.separator);
                AmLoanMainInfo mainInfo = extAmLoanMainInfoMapper.selectByLoanIdAndTenantId(mapping.getLoanId(),mapping.getTenantId());
                sb.append((mainInfo.getContractNumber()==null?"":mainInfo.getContractNumber()) + TransBizConstant.separator);
                sb.append(mapping.getLoanId() + TransBizConstant.separator);
                sb.append((mainInfo.getMerchantId()==null?"":mainInfo.getMerchantId()) + TransBizConstant.separator);
                String updateTime = DateUtils.format(log.getCreateTime(),"yyyy-MM-dd HH:mm:ss");
                sb.append(updateTime + TransBizConstant.separator);
                String loanTime = DateUtils.format(mainInfo.getTxnTime(),"yyyy-MM-dd HH:mm:ss");
                sb.append(loanTime + TransBizConstant.separator);
                String lastPaymentDate = DateUtils.format(mainInfo.getLastPaymentDate(),"yyyy-MM-dd");
                sb.append(lastPaymentDate + TransBizConstant.separator);
                CmCustomerFirstLevel firstLevel = customerService.getFirstLevelByCondition(
                        log.getCustomerId(),log.getOrganizationId(),log.getTenantId());
                sb.append(firstLevel.getChineseName() + TransBizConstant.separator);
                sb.append(firstLevel.getIdNumber() + TransBizConstant.separator);
                sb.append(mainInfo.getLoanAmount() + TransBizConstant.separator);
                sb.append(mainInfo.getInterestRate().setScale(10, BigDecimal.ROUND_HALF_UP) + TransBizConstant.separator);
                sb.append(mainInfo.getTotalTenor() + TransBizConstant.separator);//总期数
                //查询还款分配历史表
                List<TlPaymentAllocationLog> allList = extTlPaymentAllocationLogMapper.findCustLog(
                        mainInfo.getLoanId(),log.getSeqNo(),log.getCustomerId(),log.getTenantId());
                sb.append(mainInfo.getTotalTenor() + TransBizConstant.separator);

                AmLoanAccountInfo accountInfo = extAmLoanAccountInfoMapper.selectByLoanId(
                        mainInfo.getLoanId(),log.getCustomerId(),mainInfo.getTenantId());
                sb.append(accountInfo.getPrincipalBalance() + TransBizConstant.separator);
                sb.append(accountInfo.getDelqDays() + TransBizConstant.separator);

                countCmpsAmount(allList,sb);
                sb.append("回购" + TransBizConstant.separator);
                sb.append("正常");
                messageList.add(sb.toString());
            }
        }
    }

    private void createOverFileMessage(List<AmLoanAccountInfo> proList,String toDay,List<String> messageList,PrOrganizationTable org) throws TxnException {
        for(AmLoanAccountInfo info : proList){
            StringBuffer sb = new StringBuffer();
            sb.append(toDay + TransBizConstant.separator);
            AmLoanMainInfo mainInfo = extAmLoanMainInfoMapper.selectByLoanIdAndTenantId(info.getLoanId(),info.getTenantId());
            sb.append((mainInfo.getContractNumber()==null?"":mainInfo.getContractNumber()) + TransBizConstant.separator);
            sb.append(info.getLoanId() + TransBizConstant.separator);
            sb.append((mainInfo.getMerchantId()==null?"":mainInfo.getMerchantId()) + TransBizConstant.separator);
            String txnTime = DateUtils.format(mainInfo.getTxnTime(),"yyyy-MM-dd HH:mm:ss");
            sb.append(txnTime + TransBizConstant.separator);
            String lastPaymentDate = DateUtils.format(mainInfo.getLastPaymentDate(),"yyyy-MM-dd");
            sb.append(lastPaymentDate + TransBizConstant.separator);
            CmCustomerFirstLevel firstLevel = customerService.getFirstLevelByCondition(
                    info.getCustomerId(),info.getOrganizationId(),info.getTenantId());
            sb.append(firstLevel.getChineseName() + TransBizConstant.separator);
            sb.append(firstLevel.getIdNumber() + TransBizConstant.separator);
            sb.append(mainInfo.getLoanAmount() + TransBizConstant.separator);
            sb.append(mainInfo.getInterestRate().setScale(10, BigDecimal.ROUND_HALF_UP) + TransBizConstant.separator);
            sb.append(mainInfo.getTotalTenor() + TransBizConstant.separator);
            //最早逾期期次
            AmRepaymentPlanInfo plan = extAmRepaymentPlanInfoMapper.selectMaxOverPlan(
                    mainInfo.getLoanId(),mainInfo.getCustomerId(),mainInfo.getTenantId());
            sb.append(plan.getBillingTenor() + TransBizConstant.separator);
            String overDate = DateUtils.format(plan.getPaymentDueDate(),"yyyy-MM-dd");
            sb.append(overDate + TransBizConstant.separator);
            int overDays = DateUtils.getDaysBetween(plan.getPaymentDueDate(),org.getNextProcessingDate());
            sb.append(overDays + TransBizConstant.separator);
            DebtBean debtBean = debtCalculationService.getBalance(info,org.getNextProcessingDate(), true, null, null, false);
            sb.append(debtBean.getTotalAmount() + TransBizConstant.separator);
            sb.append(debtBean.getPrincipalAmount() + TransBizConstant.separator);
            sb.append(debtBean.getInterestAmount() + TransBizConstant.separator);
            sb.append(debtBean.getFeeAmount() + TransBizConstant.separator);
            sb.append(debtBean.getPenaltyAmount() + TransBizConstant.separator);
            sb.append(debtBean.getCompountAmount());

            messageList.add(sb.toString());
        }
    }

    private void createAutoPaymentFileMessage(List<TlPaymentLog> proList,String toDay,List<String> messageList) throws TxnException {
        for(TlPaymentLog log : proList){
            List<TlPaymentMapping> mappingList = extTlPaymentMappingMapper.selectByPaymentSeqAndCustomerId(log.getSeqNo(),log.getCustomerId(),log.getTenantId());

            CmCustomerFirstLevel firstLevel = customerService.getFirstLevelByCondition(
                    log.getCustomerId(),log.getOrganizationId(),log.getTenantId());

            for(TlPaymentMapping mapping : mappingList){
                StringBuffer sb = new StringBuffer();
                sb.append(toDay + TransBizConstant.separator);
                AmLoanMainInfo mainInfo = extAmLoanMainInfoMapper.selectByLoanIdAndTenantId(mapping.getLoanId(),mapping.getTenantId());
                sb.append((mainInfo.getContractNumber()==null?"":mainInfo.getContractNumber()) + TransBizConstant.separator);
                sb.append(mapping.getLoanId() + TransBizConstant.separator);
                sb.append(firstLevel.getChineseName() + TransBizConstant.separator);
                sb.append(firstLevel.getIdNumber() + TransBizConstant.separator);
                sb.append(log.getPayerAccount() + TransBizConstant.separator);
                sb.append(log.getSeqNo() + TransBizConstant.separator);
                String completeTime = DateUtils.format(log.getCompleteTime(),"yyyy-MM-dd HH:mm:ss");
                sb.append(completeTime + TransBizConstant.separator);
                sb.append("自动批扣" + TransBizConstant.separator);
                //查询还款分配历史表
                List<TlPaymentAllocationLog> allList = extTlPaymentAllocationLogMapper.findCustLog(
                        mainInfo.getLoanId(),log.getSeqNo(),log.getCustomerId(),log.getTenantId());
                BigDecimal paymentAmount = BigDecimal.ZERO;
                for(TlPaymentAllocationLog allLog : allList){
                    paymentAmount = paymentAmount.add(allLog.getPostingAmount());
                }
                sb.append(paymentAmount + TransBizConstant.separator);
                sb.append("成功");
                messageList.add(sb.toString());
            }
        }
    }

    private void countPaymentAmount(List<TlPaymentAllocationLog> allList,StringBuffer sb,TlPaymentLog log,PrShareProfitTable prShareProfitTable){
        Boolean isShareProfit = true;//是否分润
        if(TransBizConstant.REPAYMENT_TYPE_CMPS.equals(log.getPaymentType())||
                TransBizConstant.REPAYMENT_TYPE_CRT.equals(log.getPaymentType())){
            //代偿回购无需分润
            isShareProfit = false;
        }

        if(null==prShareProfitTable||TransBizConstant.NO_FLAG.equals(prShareProfitTable.getValidStatus())){
            isShareProfit = false;
        }

        BigDecimal paymentAmount = BigDecimal.ZERO;//总还款额
        BigDecimal paymentPrincipal = BigDecimal.ZERO;//总还款本金
        BigDecimal paymentInterest = BigDecimal.ZERO;//总还款利息
        BigDecimal paymentInstallmentFee = BigDecimal.ZERO;//总还款分期手续费
        BigDecimal paymentPrepayFee = BigDecimal.ZERO;//总还款提前还款手续费
        BigDecimal paymentPenalty = BigDecimal.ZERO;//总还款罚息
        BigDecimal paymentCompound = BigDecimal.ZERO;//总还款复利
        BigDecimal paymentPreoffFee= BigDecimal.ZERO;//总还款提前结清手续费

        BigDecimal shareAmount = BigDecimal.ZERO;//分润总金额
        BigDecimal shareInterest = BigDecimal.ZERO;//总应分利息
        BigDecimal shareInstallmentFee = BigDecimal.ZERO;//总应分分期手续费
        BigDecimal sharePrepayFee = BigDecimal.ZERO;//总应分提前还款手续费
        BigDecimal sharePenalty = BigDecimal.ZERO;//总应分罚息
        BigDecimal shareCompound = BigDecimal.ZERO;//总应分复利
        BigDecimal sharePreoffFee = BigDecimal.ZERO;//总应分提前结清手续费

        for(TlPaymentAllocationLog allocationLog : allList){
            if(TransBizConstant.TXN_CODE_INST_PYMT.equals(allocationLog.getTxnCode())){
                //还款本金
                paymentPrincipal = paymentPrincipal.add(allocationLog.getPostingAmount());
            }else if(TransBizConstant.TXN_CODE_INST_PYMT_INTR.equals(allocationLog.getTxnCode())){
                //还款利息
                paymentInterest = paymentInterest.add(allocationLog.getPostingAmount());
                //计算利息分润值
                if(isShareProfit){
                    if(TransBizConstant.PARTNER_SHARE_UNIT_1.equals(prShareProfitTable.getInterestShareUnit())){
                        shareInterest = shareInterest.add(prShareProfitTable.getInterestShareValue());
                    }else if(TransBizConstant.PARTNER_SHARE_UNIT_0.equals(prShareProfitTable.getInterestShareUnit())){
                        BigDecimal intValue = allocationLog.getPostingAmount().multiply(prShareProfitTable.getInterestShareValue());
                        shareInterest = shareInterest.add(intValue);
                    }
                }
            }else if(TransBizConstant.TXN_CODE_INST_PYMT_FEE.equals(allocationLog.getTxnCode())) {
                //分期手续费
                paymentInstallmentFee = paymentInstallmentFee.add(allocationLog.getPostingAmount());
                //计算分期手续费分润值
                if(isShareProfit){
                    if(TransBizConstant.PARTNER_SHARE_UNIT_1.equals(prShareProfitTable.getInstallmentFeeShareUnit())){
                        shareInstallmentFee = shareInstallmentFee.add(prShareProfitTable.getInstallmentFeeShareValue());
                    }else if(TransBizConstant.PARTNER_SHARE_UNIT_0.equals(prShareProfitTable.getInterestShareUnit())){
                        BigDecimal installmentFeeValue = allocationLog.getPostingAmount().multiply(prShareProfitTable.getInstallmentFeeShareValue());
                        shareInstallmentFee = shareInstallmentFee.add(installmentFeeValue);
                    }
                }
            }else if(TransBizConstant.TXN_CODE_INST_PYMT_PREPAY_FEE.equals(allocationLog.getTxnCode())) {
                //提前还款手续费
                paymentPrepayFee = paymentPrepayFee.add(allocationLog.getPostingAmount());
                //计算提前还款手续费分润值
                if(isShareProfit){
                    if(TransBizConstant.PARTNER_SHARE_UNIT_1.equals(prShareProfitTable.getPrepayFeeShareUnit())){
                        sharePrepayFee = sharePrepayFee.add(prShareProfitTable.getPrepayFeeShareValue());
                    }else if(TransBizConstant.PARTNER_SHARE_UNIT_0.equals(prShareProfitTable.getInterestShareUnit())){
                        BigDecimal prepayFeeValue = allocationLog.getPostingAmount().multiply(prShareProfitTable.getPrepayFeeShareValue());
                        sharePrepayFee = sharePrepayFee.add(prepayFeeValue);
                    }
                }
            }else if(TransBizConstant.TXN_CODE_INST_PYMT_PEN_INTR.equals(allocationLog.getTxnCode())) {
                //罚息
                paymentPenalty = paymentPenalty.add(allocationLog.getPostingAmount());
                //计算罚息分润值
                if(isShareProfit){
                    if(TransBizConstant.PARTNER_SHARE_UNIT_1.equals(prShareProfitTable.getPenaltyShareUnit())){
                        sharePenalty = sharePenalty.add(prShareProfitTable.getPenaltyShareValue());
                    }else if(TransBizConstant.PARTNER_SHARE_UNIT_0.equals(prShareProfitTable.getInterestShareUnit())){
                        BigDecimal penaltyValue = allocationLog.getPostingAmount().multiply(prShareProfitTable.getPenaltyShareValue());
                        sharePenalty = sharePenalty.add(penaltyValue);
                    }
                }
            }else if(TransBizConstant.TXN_CODE_INST_PYMT_COM_INTR.equals(allocationLog.getTxnCode())) {
                //复利
                paymentCompound = paymentCompound.add(allocationLog.getPostingAmount());
                //计算复利分润值
                if(isShareProfit){
                    if(TransBizConstant.PARTNER_SHARE_UNIT_1.equals(prShareProfitTable.getCompoundShareUnit())){
                        shareCompound = shareCompound.add(prShareProfitTable.getCompoundShareValue());
                    }else if(TransBizConstant.PARTNER_SHARE_UNIT_0.equals(prShareProfitTable.getCompoundShareUnit())){
                        BigDecimal compoundValue = allocationLog.getPostingAmount().multiply(prShareProfitTable.getCompoundShareValue());
                        shareCompound = shareCompound.add(compoundValue);
                    }
                }
            }else if(TransBizConstant.TXN_CODE_INST_PYMT_PAYOFF_FEE.equals(allocationLog.getTxnCode())) {
                //提前结清手续费
                paymentPreoffFee = paymentPreoffFee.add(allocationLog.getPostingAmount());
                //计算提前结清手续费分润值
                if(isShareProfit){
                    if(TransBizConstant.PARTNER_SHARE_UNIT_1.equals(prShareProfitTable.getPreoffFeeShareUnit())){
                        sharePreoffFee = sharePreoffFee.add(prShareProfitTable.getPreoffFeeShareValue());
                    }else if(TransBizConstant.PARTNER_SHARE_UNIT_0.equals(prShareProfitTable.getPreoffFeeShareUnit())){
                        BigDecimal preoffValue = allocationLog.getPostingAmount().multiply(prShareProfitTable.getPreoffFeeShareValue());
                        sharePreoffFee = sharePreoffFee.add(preoffValue);
                    }
                }
            }
        }
        paymentAmount = paymentPrincipal.add(paymentInterest).add(paymentInstallmentFee).add(paymentPrepayFee).
                add(paymentPenalty).add(paymentCompound).add(paymentPreoffFee);
        shareAmount = shareInterest.add(shareInstallmentFee).add(sharePrepayFee).add(sharePenalty).add(shareCompound).add(sharePreoffFee);

        sb.append(paymentAmount + TransBizConstant.separator);
        sb.append(paymentPrincipal + TransBizConstant.separator);
        sb.append(paymentInterest + TransBizConstant.separator);
        sb.append(paymentInstallmentFee + TransBizConstant.separator);
        sb.append(paymentPrepayFee + TransBizConstant.separator);
        sb.append(paymentPenalty + TransBizConstant.separator);
        sb.append(paymentCompound + TransBizConstant.separator);
        sb.append(paymentPreoffFee + TransBizConstant.separator);
        sb.append(shareAmount + TransBizConstant.separator);
        sb.append(shareInterest + TransBizConstant.separator);
        sb.append(shareInstallmentFee + TransBizConstant.separator);
        sb.append(sharePrepayFee + TransBizConstant.separator);
        sb.append(sharePenalty + TransBizConstant.separator);
        sb.append(shareCompound + TransBizConstant.separator);
        sb.append(sharePreoffFee + TransBizConstant.separator);
    }

    private void countCmpsAmount(List<TlPaymentAllocationLog> allList,StringBuffer sb){
        BigDecimal paymentAmount = BigDecimal.ZERO;//总还款额
        BigDecimal paymentPrincipal = BigDecimal.ZERO;//总还款本金
        BigDecimal paymentInterest = BigDecimal.ZERO;//总还款利息
        BigDecimal paymentInstallmentFee = BigDecimal.ZERO;//总还款分期手续费
        BigDecimal paymentPrepayFee = BigDecimal.ZERO;//总还款提前还款手续费
        BigDecimal paymentPenalty = BigDecimal.ZERO;//总还款罚息
        BigDecimal paymentCompound = BigDecimal.ZERO;//总还款复利
        BigDecimal paymentPreoffFee= BigDecimal.ZERO;//总还款提前结清手续费


        for(TlPaymentAllocationLog allocationLog : allList){
            if(TransBizConstant.TXN_CODE_INST_PYMT.equals(allocationLog.getTxnCode())){
                //还款本金
                paymentPrincipal = paymentPrincipal.add(allocationLog.getPostingAmount());
            }else if(TransBizConstant.TXN_CODE_INST_PYMT_INTR.equals(allocationLog.getTxnCode())){
                //还款利息
                paymentInterest = paymentInterest.add(allocationLog.getPostingAmount());
            }else if(TransBizConstant.TXN_CODE_INST_PYMT_FEE.equals(allocationLog.getTxnCode())) {
                //分期手续费
                paymentInstallmentFee = paymentInstallmentFee.add(allocationLog.getPostingAmount());
            }else if(TransBizConstant.TXN_CODE_INST_PYMT_PREPAY_FEE.equals(allocationLog.getTxnCode())) {
                //提前还款手续费
                paymentPrepayFee = paymentPrepayFee.add(allocationLog.getPostingAmount());
            }else if(TransBizConstant.TXN_CODE_INST_PYMT_PEN_INTR.equals(allocationLog.getTxnCode())) {
                //罚息
                paymentPenalty = paymentPenalty.add(allocationLog.getPostingAmount());
            }else if(TransBizConstant.TXN_CODE_INST_PYMT_COM_INTR.equals(allocationLog.getTxnCode())) {
                //复利
                paymentCompound = paymentCompound.add(allocationLog.getPostingAmount());
            }else if(TransBizConstant.TXN_CODE_INST_PYMT_PAYOFF_FEE.equals(allocationLog.getTxnCode())) {
                //提前结清手续费
                paymentPreoffFee = paymentPreoffFee.add(allocationLog.getPostingAmount());
            }
        }
        paymentAmount = paymentPrincipal.add(paymentInterest).add(paymentInstallmentFee).add(paymentPrepayFee).
                add(paymentPenalty).add(paymentCompound).add(paymentPreoffFee);
        sb.append(paymentAmount + TransBizConstant.separator);
        sb.append(paymentPrincipal + TransBizConstant.separator);
        sb.append(paymentInterest + TransBizConstant.separator);
        sb.append(paymentInstallmentFee + TransBizConstant.separator);
        sb.append(paymentPenalty + TransBizConstant.separator);
        sb.append(paymentCompound + TransBizConstant.separator);
    }

    private void generatingFile(List<String> messageList,String basePath,String fileName){
        Path verifyFile = Paths.get(basePath + fileName);

        Integer i = 0;
        try(FileWriter bfw = new FileWriter(verifyFile.toFile(),true);
            BufferedWriter writer = new BufferedWriter(bfw,10240)) {
            if(verifyFile.toFile().length() != 0){
                writer.write("\r\n");
            }
            for (String message : messageList) {
                i++;
                if(i == messageList.size()){
                    writer.write(message);
                }else{
                    writer.write(message + "\r\n");
                }
            }
            writer.flush();
        } catch (IOException e) {
            logger.error("生成对账文件异常，异常信息：",e);
            throw new RuntimeException(e);
        }
    }

    private void mergeVerifyFile(String verifyPath,String fileType)  {
        //获取目录下所有文件
        File file = new File(verifyPath);
        File[] tempList = file.listFiles();
        if(tempList == null || tempList.length == 0){
            logger.error("文件合并，未获取到需要合并的文件");
            throw new RuntimeException("文件合并，未获取到需要合并的文件");
        }

        List<File> mergeList = new ArrayList<>();

        for(int i = 0; i < tempList.length; i++){
            String fileName = tempList[i].getName();
            if(fileName.length() < fileType.length()){
                continue;
            }
            String subStr = fileName.substring(0,fileType.length());
            if(fileType.equals(subStr)){
                mergeList.add(tempList[i]);
            }
        }
        //合并文件
        File resultFile = new File(verifyPath + fileType + ".txt");

        Boolean isNullFile = true;
        try(FileChannel resultFileChannel= new FileOutputStream(resultFile, true).getChannel()){
            for(int i = 0; i < mergeList.size(); i++){
                FileChannel blk1 = new FileInputStream(mergeList.get(i)).getChannel();
                if(i == 0 && blk1.size() == 0){
                    resultFile.createNewFile();
                }else if (blk1.size() != 0){
                    if(!isNullFile && i != 0){
                        //换行
                        ByteBuffer buf = ByteBuffer.allocate(48);
                        buf.clear();
                        buf.put("\r\n".getBytes());
                        buf.flip();
                        while(buf.hasRemaining()) {
                            resultFileChannel.write(buf);
                        }
                    }
                    //写入新文件
                    resultFileChannel.transferFrom(blk1, resultFileChannel.size(), blk1.size());
                    isNullFile = false;
                }
                blk1.close();
            }
        } catch (IOException e) {
            logger.error("对账文件合并异常，异常信息：",e);
            throw new RuntimeException(e);
        }
    }

    private void uploadFile(List<String> uploadFileLists,PrVerifyFileTable verifyFileTable,String verifyPath,PrOrganizationTable org,String proId) throws Exception {
        logger.debug("开始上传合作方对账文件");
        File file = new File(verifyPath);
        File[] tempList = file.listFiles();

        //1 获取连接
        SftpUtils.sftpConnect(verifyFileTable.getUploadUserName(),
                verifyFileTable.getUploadPassword(),verifyFileTable.getUploadHost(), Integer.parseInt(verifyFileTable.getUploadPort()));

        //2 检查创建目录
        String today = DateUtils.format(org.getToday(),"yyyyMMdd");
        String directory = verifyFileTable.getUploadPath() + org.getTenantId() + "/" + today;
        SftpUtils.createDir(directory);

        //3 上传文件
        for(File uploadFile : tempList){
            String filename = uploadFile.getName();
            if(uploadFileLists.contains(filename)){
                SftpUtils.sftpUpload(uploadFile);
            }
        }
        String okName = proId + "_" + today + ".ok";
        //上传OK文件
        for(File uploadFile : tempList){
            String filename = uploadFile.getName();
            if(okName.equals(filename)){
                SftpUtils.sftpUpload(uploadFile);
            }
        }

        //4 关闭连接
        SftpUtils.disSftpConnect();
    }
}
